import type { PlatformEventConfig } from '../../../types/constants/event'
import type { ComponentStyleIdType } from '../../../types/interfaces'
import { BaseModule } from '../../../lib/abstract'
import { EventHandler } from '../../../lib/event_handler'
import { GithubPageType } from '../../../lib/page_handler/platform/github/types'
import { GreasyForkPageType } from '../../../lib/page_handler/platform/greasyfork/types'
import { ToolKit } from '../../../lib/utils/toolkit'
import { PreventionScenario } from '../../../lib/utils/ui/event'
import {
  ComponentStyleId,
  logger,
  SUPPORTED_PLATFORMS,
} from '../../../types/constants'
import { ConfigManager } from '../../config_manager'

interface Config {
  enabled?: boolean
}

export class NewTabLinks extends BaseModule {
  readonly id: string = 'new_tab_links'
  readonly styleId: string = ComponentStyleId[this.name]
  isInitialized: boolean = false
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  private static instance: NewTabLinks
  private readonly eventHandler: EventHandler | undefined
  private readonly EVENT_NAMESPACE = 'newTabLinks'
  private readonly eventConfig: PlatformEventConfig = {}

  config: Config = {
    enabled: true,
  }

  get name(): ComponentStyleIdType {
    return 'NewTabLinks'
  }

  constructor() {
    super()

    // 油叉论坛及其筛选子页面的配置
    const defaultGreasyForkDiscussionConfig = {
      selector: '.discussion-list .discussion-list-container .discussion-title',
      eventType: 'click',
      handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
    }

    this.eventConfig = {
      [SUPPORTED_PLATFORMS.GREASY_FORK]: {
        // 测试链接：https://greasyfork.org/zh-CN
        [GreasyForkPageType.INDEX]: [
          {
            selector: '.text-content a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // 测试链接：
        // 1）https://greasyfork.org/zh-CN/scripts
        // 2）https://greasyfork.org/zh-CN/scripts/by-site/bilibili.com
        [GreasyForkPageType.SCRIPT_LIST]: [
          {
            selector: '#browse-script-list li article dd.script-list-author a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
          {
            selector: '#browse-script-list li article a.script-link',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // 测试链接：https://greasyfork.org/zh-CN/scripts/546375
        [GreasyForkPageType.SCRIPT_INFO]: [
          {
            selector: '#script-content a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // 测试链接：https://greasyfork.org/zh-CN/scripts/498197-auto-skip-youtube-ads/feedback
        [GreasyForkPageType.SCRIPT_FEEDBACK]: [
          {
            selector: '.script-discussion-list .discussion-list-container .discussion-title',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // 测试链接：https://greasyfork.org/zh-CN/discussions
        [GreasyForkPageType.DISCUSSIONS]: [
          defaultGreasyForkDiscussionConfig,
        ],
        [GreasyForkPageType.DISCUSSIONS_GREASY_FORK]: [
          defaultGreasyForkDiscussionConfig,
        ],
        [GreasyForkPageType.DISCUSSIONS_DEVELOPMENT]: [
          defaultGreasyForkDiscussionConfig,
        ],
        [GreasyForkPageType.DISCUSSIONS_REQUESTS]: [
          defaultGreasyForkDiscussionConfig,
        ],
        [GreasyForkPageType.DISCUSSIONS_SCRIPT]: [
          defaultGreasyForkDiscussionConfig,
        ],
        [GreasyForkPageType.DISCUSSIONS_NO_SCRIPT]: [
          defaultGreasyForkDiscussionConfig,
        ],
        // 测试链接：https://greasyfork.org/zh-CN/search
        [GreasyForkPageType.SEARCH]: [
          {
            selector: '#script-search input.search-submit',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleSearchSubmit('#script-search', e),
          },
          {
            selector: '#library-search input.search-submit',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleSearchSubmit('#library-search', e),
          },
          {
            selector: '#code-search input.search-submit',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleSearchSubmit('#code-search', e),
          },
          {
            selector: '#user-search input.search-submit',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleSearchSubmit('#user-search', e),
          },
        ],
        // 测试链接：https://greasyfork.org/zh-CN/moderator_actions
        [GreasyForkPageType.MODERATOR_ACTIONS]: [
          {
            selector: 'table.text-content a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // 测试链接：https://greasyfork.org/zh-CN/reports/85828
        [GreasyForkPageType.REPORTS]: [
          {
            selector: '.text-content a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // 测试链接：https://greasyfork.org/zh-CN/help
        [GreasyForkPageType.HELP]: [
          {
            selector: '.text-content a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // 测试链接：https://greasyfork.org/zh-CN/scripts/by-site
        [GreasyForkPageType.BY_SITE]: [
          {
            selector: '.text-content a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
        // https://greasyfork.org/zh-CN/users/364215-ricsy
        [GreasyForkPageType.USER_PROFILE]: [
          {
            selector: '#user-control-panel a',
            eventType: 'click',
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
      },
      [SUPPORTED_PLATFORMS.GITHUB]: {
        // 测试链接：https://github.com/lisonge/vite-plugin-monkey
        [GithubPageType.Project]: [
          {
            selector: 'article.markdown-body a',
            eventType: 'click',
            capture: true, // 捕获阶段就开始处理
            handler: (e: JQuery.ClickEvent) => this.handleUrlClick(true, e),
          },
        ],
      },
    }

    this.eventHandler = new EventHandler(this.eventConfig, this.EVENT_NAMESPACE, true)
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): NewTabLinks {
    if (!NewTabLinks.instance) {
      NewTabLinks.instance = new NewTabLinks()
    }
    return NewTabLinks.instance
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.setupEventListeners()
  }

  onToggleCallback(_id: string, checked: boolean): void {
    super.onToggleCallback(_id, checked)
  }

  handleCleanupOthers(): void {
    this.eventHandler?.destroy()
  }

  setupEventListeners(): void {
    this.eventHandler?.init()
  }

  /**
   * 处理链接点击事件
   */
  private handleUrlClick(prependOrigin: boolean = true, e: JQuery.ClickEvent): void {
    ToolKit.ui.event.preventEventByScenario(e, PreventionScenario.Link)

    const $el = $(e.target)
    const url = $el.attr('href') || ''

    if (!ToolKit.browser.url.isValidHref(url))
      return

    ToolKit.browser.url.openNewTab(ToolKit.browser.url.getFullUrl(url, prependOrigin))
  }

  /**
   * 处理搜索提交点击事件
   */
  private handleSearchSubmit(selector: string, e: JQuery.ClickEvent): void {
    e.preventDefault()

    const $element = $(e.currentTarget)
    const formAction = $element.closest(selector).attr('action') || ''

    if (!formAction)
      return

    const $search = $element.siblings('input[type="search"]')
    const param = $search.attr('name') || 'q'
    const keyword = $search.val()
    ToolKit.browser.url.openNewTab(ToolKit.browser.url.getFullUrl(`${formAction}?${param}=${keyword}`))
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.setupEventListeners()

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }

  getStyles(): string {
    return `
`
  }
}
